package settings

import (
	"code.google.com/p/jesus-1496/utils/env"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"path"
)

var (
	authSettingsMinBcryptCost = 10
	authSettingsMaxBcryptCost = 31
)

type settings struct {
	Auth   authSettings
	Server serverSettings
	Web    webSettings
	Rpc    rcpSettings
	Db     dbSettings
}

type authSettings struct {
	BcryptCost        int
	MinPasswordLength int
	MaxPasswordLength int
}

type serverSettings struct {
	ListenIp   string
	ListenPort int
}

type webSettings struct {
	HomeUrl string
}

type rcpSettings struct {
	Ip   string
	Port int
}

type dbSettings struct {
	Username string
	Password string
	DbName   string
	Address  string
	Port     int
}

var Settings *settings
var settingsFile string = path.Join(env.GetProjectDir(), "settings", "settings.js")

type SettingsError error

func NewSettingsError(s string) error {
	return errors.New(fmt.Sprintf("SettingsError: %s.", s))
}

func newSettings() *settings {
	//return &settings{authSettings{}, serverSettings{}, webSettings{}, rcpSettings{}, databaseSettings{}}
	return &settings{}
}

func openAndReadSettingsFile(filename string) (*settings, error) {
	fileBytes, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	ret := newSettings()
	err = json.Unmarshal(fileBytes, &ret)
	if err != nil {
		return nil, err
	}
	err = ret.validate()
	if err != nil {
		return nil, err
	}

	return ret, nil
}

func (s *settings) validate() error {
	if s.Auth.BcryptCost < authSettingsMinBcryptCost || s.Auth.BcryptCost > authSettingsMaxBcryptCost {
		return NewSettingsError(fmt.Sprintf("Auth.BcryptCost: got %d, want between %d and %d.", s.Auth.BcryptCost, authSettingsMinBcryptCost, authSettingsMaxBcryptCost))
	}

	if s.Auth.MinPasswordLength >= s.Auth.MaxPasswordLength {
		return NewSettingsError(fmt.Sprintf("Auth.(Min/Max)PasswordLength: Min should be smaller than Max. Min: %d, Max: %d.", s.Auth.MinPasswordLength, s.Auth.MaxPasswordLength))
	}

	//Maybe need some way of validating settings from outside of this module
	return nil
}

func init() {
	var err error = nil
	Settings, err = openAndReadSettingsFile(settingsFile)
	if err != nil {
		panic(err.Error())
	}
	//Cannot use serverlogger as it depends on settings.
	fmt.Printf("Settings parsed correctly: Settings = %+v.\n", Settings)
}
